import OSS from 'ali-oss';
import JSZip from "jszip";
import * as uuid from 'uuid';

import { ElMessage } from 'element-plus';
import saveAs from 'file-saver';
import { assign } from 'underscore';
import { asyncselectmatchquestion, ossupload } from '../api/index';
import Studycodemodel from '../mysql_interface/studycodemodel';
import { isOut } from './RegExp';

export default async function updateoss(files: File[], insert?: (str: string) => void) {
  const res: any = await ossupload()
  const client = new OSS({
    region: "oss-cn-qingdao",
    accessKeyId: res.accessKeyId,
    accessKeySecret: res.accessKeySecret,
    stsToken: res.securityToken,
    bucket: "cdn-hterobot"
  });
  const x = files[0].name.split(".");
  const name = x[x.length - 1];
  const url = `school/${uuid.v4()}.${name}`;

  if (insert) {
    const data = await client.put(url, files[0]);
    insert(`https://cdn.hterobot.com/${url}`);
    return data
  } else {
    return client.put(url, files[0])
  }
}


export async function updateoss2(files: File[], option = { bucket: 'cdn-hterobot', url: '', res: { accessKeyId: '', accessKeySecret: '', securityToken: '' } }, insert?: (str: OSS.MultipartUploadResult) => void, multipart?: OSS.MultipartUploadOptions) {
  let { bucket, url, res } = option
  const client = new OSS({
    region: "oss-cn-qingdao",
    accessKeyId: res.accessKeyId,
    accessKeySecret: res.accessKeySecret,
    stsToken: res.securityToken,
    bucket,
  });
  const x = files[0].name.split(".");
  const name = x[x.length - 1];
  if (!url) {
    url = `school/${uuid.v4()}.${name}`;
  }

  if (insert) {
    const data = await client.multipartUpload(url, files[0], assign({}, multipart));
    insert(data);
    return data
  } else {
    return client.multipartUpload(url, files[0], assign({}, multipart))
  }
}

export async function updatezip(file: File) {

  const zip = await JSZip.loadAsync(file);
  const obj: {
    [key: string]: Studycodemodel.Itestcases;
  } = {};
  const uu = uuid.v4()
  const d: JSZip.JSZipObject[] = [];
  zip.forEach((rp, z) => {
    d.push(z);
  });
  const res: any = await ossupload()
  const client = new OSS({
    region: "oss-cn-qingdao",
    accessKeyId: res.accessKeyId,
    accessKeySecret: res.accessKeySecret,
    stsToken: res.securityToken,
    bucket: "cdn-hterobot"
  });

  for (const iterator of d) {
    let { name } = iterator
    name = name.toLowerCase()
    const _in = new RegExp(/\.in$/);
    const out = isOut;

    if (_in.test(name)) {
      const files = await iterator.async("blob")
      const url = `noip/${uu}/${name}`;
      await client.put(url, files);
      const text = `https://cdn.hterobot.com/${url}`
      const tmp = obj[name.replace(_in, "")];
      if (tmp) {
        obj[name.replace(_in, "")].input = text;
      } else {
        obj[name.replace(_in, "")] = {
          input: text,
          output: undefined,
          type: 'url',
          isshow: true
        };
      }
    }
    if (out.test(name)) {
      const files = await iterator.async("blob")
      const url = `noip/${uu}/${name}`;
      await client.put(url, files);
      const text = `https://cdn.hterobot.com/${url}`
      const tmp = obj[name.replace(out, "")];
      if (tmp) {
        obj[name.replace(out, "")].output = text;
      } else {
        obj[name.replace(out, "")] = {
          input: undefined,
          output: text,
          type: 'url',
          isshow: true
        };
      }
    }
  }
  console.log(obj)
  const data: Studycodemodel.Itestcases[] = []

  return Object.values(obj).sort((a, b) => Number(a.input?.split('/').pop()?.replace(/[^0-9]/ig, '')) - Number(b.input?.split('/').pop()?.replace(/[^0-9]/ig, '')));
}

export async function downloadexamplezip(example: Studycodemodel.Itestcases[], name = '未命名.zip') {

  if (example && example.length) {
    const zip = new JSZip();
    let i = 1;
    for (const v of example) {
      let { input = "", output = "", type } = v;
      if (type === "url") {
        try {
          let url = new URL(input)
          url.protocol = 'https:'
          input = url.href
          const io = await fetch(input, {
            headers: {
              'Access-Control-Allow-Origin': '*'
            }
          })
          const ifile = await io.arrayBuffer()
          zip.file(`${i}.in`, ifile);
        } catch (e) {

        }
        try {
          let url = new URL(output)
          url.protocol = 'https:'
          output = url.href
          const o = await fetch(output, {
            headers: {
              'Access-Control-Allow-Origin': '*'
            }
          })
          const ofile = await o.arrayBuffer()
          zip.file(`${i}.out`, ofile);
        } catch (e) {

        }

      } else {
        zip.file(`${i}.in`, input);
        zip.file(`${i}.out`, output);
      }
      i++;
    }
    zip.generateAsync({ type: "blob" }).then(
      function (blob) {
        const reader = new FileReader();
        reader.readAsDataURL(blob);
        reader.onload = function (e) {
          const a = document.createElement("a");
          a.download = name;
          if (e.target) {
            a.href = e.target.result as string;
          } else {
            a.href = location.href;
          }
          a.click();
          a.remove();
        };
      },
      function (err) {
        ElMessage.error("下载失败");
      }
    );
  }
}

export async function _downloadexamplezip(example: Studycodemodel.Itestcases[], zip: JSZip, name?: string) {
  if (example && example.length) {
    let i = 1;
    for (const v of example) {
      const n = name ? name + '/' + i : i
      let { input = "", output = "", type } = v;
      if (type === "url") {
        try {
          let url = new URL(input)
          url.protocol = 'https:'
          input = url.href
          const io = await fetch(input, {
            headers: {
              'Access-Control-Allow-Origin': '*'
            }
          })
          const ifile = await io.arrayBuffer()
          zip.file(`${n}.in`, ifile);
        } catch (e) {

        }
        try {
          let url = new URL(output)
          url.protocol = 'https:'
          output = url.href
          const o = await fetch(output, {
            headers: {
              'Access-Control-Allow-Origin': '*'
            }
          })
          const ofile = await o.arrayBuffer()
          zip.file(`${n}.out`, ofile);
        } catch (e) {

        }

      } else {
        zip.file(`${n}.in`, input);
        zip.file(`${n}.out`, output);
      }
      i++;
    }
  }
  return zip
}


export async function downloadmatchquestion(p: any, test = false) {
  const e = await asyncselectmatchquestion({ activityid: p.data.ID })
  const zip = new JSZip()
  const [data] = e
  const matchquestion = data.matchquestion || []
  for (const a of matchquestion) {
    let json = `
## 题目类型
${a.type ? a.type : ''}

## 题目名称
${a.name ? a.name : ''}

## 题目难度
${a.difficulty ? a.difficulty : ''}

## 题目背景
${a.background ? a.background : ''}

## 题目描述
${a.context ? a.context : ''}

## 输入格式
${a.inputformat ? a.inputformat : ''}

## 输出格式
${a.outputformat ? a.outputformat : ''}

## 说明
${a.tips ? a.tips : ''}

          `
    const example = a.exampletest?.map((a, k) => {
      return `
## 样例 $${k + 1}$ 输入   
${a.input ? a.input : ''}

## 样例 $${k + 1}$ 输出
${a.output ? a.output : a.output}

              `
    }).join('\r') || ''

    zip.file(a.name + '.md', json.concat(example))
    if (test) {
      await _downloadexamplezip(a.example || [], zip, a.name)
    }
  }

  const buf = await zip.generateAsync({ type: "blob" })
  saveAs(buf, `${p.data.name}.zip`)
}

export interface UploadBlobToOSSResult {
  name: string; // The object key in OSS
  url: string; // The CDN URL
  res: OSS.NormalSuccessResponse['res']; // The raw response from OSS SDK
}

export async function uploadBlobToOSS(
  blob: Blob,
  fileName: string,
  options: {
    bucket?: string;
    pathPrefix?: string;
  } = {}
): Promise<UploadBlobToOSSResult> {
  // Always fetch credentials from ossupload()
  const resToken: any = await ossupload();
  const { bucket = 'cdn-hterobot', pathPrefix = 'school/uploads/' } = options;

  const client = new OSS({
    region: "oss-cn-qingdao", // Consider making region configurable if needed
    accessKeyId: resToken.accessKeyId,
    accessKeySecret: resToken.accessKeySecret,
    stsToken: resToken.securityToken,
    bucket: bucket,
  });

  const uniqueFileName = `${uuid.v4()}-${fileName}`;
  const fullPath = `${pathPrefix.endsWith('/') ? pathPrefix : pathPrefix + '/'}${uniqueFileName}`;

  try {
    const result = await client.put(fullPath, blob);
    // Construct the CDN URL. This might vary based on your CDN setup.
    const cdnUrl = `https://cdn.hterobot.com/${fullPath}`;
    return {
      name: fullPath, // This is the object key
      url: cdnUrl,
      res: result.res,
    };
  } catch (error: any) { // Added type annotation for error
    console.error("OSS uploadBlobToOSS Error:", error);
    ElMessage.error(`上传文件到OSS失败: ${error.message || '未知错误'}`);
    throw error; // Re-throw the error so the caller can handle it
  }
}

